package pe.gob.osinergmin.activity;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;

import org.apache.http.Header;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import pe.gob.osinergmin.R;
import pe.gob.osinergmin.activity.generic.GenericActivity;
import pe.gob.osinergmin.bean.common.OrdenPedido;
import pe.gob.osinergmin.bean.common.UnidadOperativa;
import pe.gob.osinergmin.bean.common.Usuario;
import pe.gob.osinergmin.service.UsuarioService;
import pe.gob.osinergmin.utils.PuntoControlConstants;
import pe.gob.osinergmin.utils.PuntoControlUpdateControl;
import pe.gob.osinergmin.utils.PuntoControlUtils;

import static pe.gob.osinergmin.utils.PuntoControlConstants.SESSION_USER_VAR;

public class LoginActivity extends GenericActivity implements OnClickListener{

    private EditText txtUsuario;
    private EditText txtClave;
    private ImageView imgVisibility;
    private Usuario usuario;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.login);

        Button btnLogin = (Button) findViewById(R.id.btnLogin);
        btnLogin.setOnClickListener(this);

        imgVisibility = (ImageView) findViewById(R.id.txtClave_visibility);

        txtUsuario = (EditText) findViewById(R.id.txtUsuario);

        txtClave = (EditText) findViewById(R.id.txtClave);
        txtClave.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                imgVisibility.setVisibility(s.length() > 0 ? View.VISIBLE : View.INVISIBLE);
            }
        });

        imgVisibility.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                final boolean isOutsideView = event.getX() < 0 || event.getX() > v.getWidth() || event.getY() < 0 || event.getY() > v.getHeight();
                final int cursor = txtClave.getSelectionStart();

                if(isOutsideView || MotionEvent.ACTION_UP == event.getAction()){
                    imgVisibility.setImageDrawable(getResources().getDrawable(R.drawable.ic_show_password));
                    txtClave.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
                }else{
                    imgVisibility.setImageDrawable(getResources().getDrawable(R.drawable.ic_hide_password));
                    txtClave.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
                }

                txtClave.setSelection(cursor);

                return true;
            }
        });
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        try {
            usuario = getUsuarioService().findUsuario(this);
        } catch (Exception e) {
            e.printStackTrace();
        }

        boolean hasConnection = PuntoControlUtils.validateConnectivity(this);
        if(!hasConnection && usuario != null){
            showMenu();
        }
    }

    @Override
    public void onClick(View view) {
        hideSoftKeyboard(view);
        String _usuario = txtUsuario.getText().toString();
        String _clave = txtClave.getText().toString();

        Usuario fUsuario = new Usuario(_usuario, _clave);

        try {
            if(!PuntoControlUtils.validateConnectivity(this)) {
                usuario = getUsuarioService().findUsuario(this);
            }else{
                usuario = null;
            }

            if (usuario == null) {
                if(PuntoControlUtils.validateConnectivity(this)) {
                    findUserOnServer(this, fUsuario);
                }else{
                    makeText(this, "No se cuenta con conexión de internet para autenticar", Toast.LENGTH_SHORT);
                }
            }else{
                if(PuntoControlUtils.validateConnectivity(this)){
                    List<UnidadOperativa> unidadOperativaList = getUnidadOperativaService().getUnidadOperativaList(this, null);
                    if(unidadOperativaList == null || unidadOperativaList.size() == 0){
                        findUnidadOperativa(this);
                    }
                }else {
                    showMenu();
                }
            }
        } catch (Exception e) {
            makeText(getBaseContext(), R.string.error_internal, Toast.LENGTH_SHORT);
        }

    }

    private void showMenu(){
        Intent intent = new Intent(this, MenuActivity.class);
        intent.putExtra(SESSION_USER_VAR, usuario);
        startActivity(intent);
    }

    public void findUserOnServer(final Context context, final Usuario fusuario){
        final UsuarioService usuarioService = getUsuarioService();
        PuntoControlUtils.getProgressDialog(context, getResources().getString(R.string.waiting_load_usuario)).show();

        AsyncHttpClient client = new AsyncHttpClient();
        String url = MessageFormat.format(PuntoControlConstants.URL_USUARIO_LOGIN, fusuario.getUsername());
        client.get(url,null ,new AsyncHttpResponseHandler() {

            @Override
            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                try {
                    // JSON Object
                    JSONObject obj = new JSONObject(new String(responseBody));
                    Usuario nusuario = new Usuario();
                    nusuario.setUsername(obj.getString("username"));
                    nusuario.setPassword(obj.getString("password"));
                    nusuario.setNombre(obj.getString("nombre"));
                    nusuario.setApellidoPaterno(obj.getString("apellidoPaterno"));
                    nusuario.setApellidoMaterno(obj.getString("apellidoMaterno"));

                    PuntoControlUtils.getProgressDialog().dismiss();
                    if (nusuario.getUsername() == null || "".equals(nusuario.getUsername())) {
                        makeText(context, R.string.error_invalid_user, Toast.LENGTH_SHORT);
                    } else {
                        if(fusuario.getPassword().equals(nusuario.getPassword())){
                            try {
                                usuarioService.saveUsuarioToLocal(context, nusuario);
                            }catch(Exception e) {
                                makeText(context, e.getMessage(), Toast.LENGTH_LONG);
                            }
                            usuario = nusuario;
                            PuntoControlUtils.getProgressDialog().dismiss();
                            findUnidadOperativa(context);
                        }else{
                            makeText(context, R.string.error_invalid_password, Toast.LENGTH_SHORT);
                        }
                    }
                } catch (JSONException e) {
                    PuntoControlUtils.getProgressDialog().dismiss();
                    makeText(context, R.string.error_json_generic, Toast.LENGTH_LONG);
                }
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
                PuntoControlUtils.getProgressDialog().dismiss();
                if(statusCode == 404){
                    makeText(context, R.string.error_http_404, Toast.LENGTH_LONG);
                }
                // When Http response code is '500'
                else if(statusCode == 500){
                    makeText(context, R.string.error_http_500, Toast.LENGTH_LONG);
                }
                // When Http response code other than 404, 500
                else{
                    makeText(context, R.string.error_http_other, Toast.LENGTH_LONG);
                }
            }
        });
    }

    public void findUnidadOperativa(Context context){

        if(PuntoControlUtils.validateConnectivity(this)){
            PuntoControlUpdateControl updateControl = new PuntoControlUpdateControl(this);
            String lastUpdate = updateControl.getLastUpdateDate();
            String today = PuntoControlUtils.getDateFormatter(new Date());
            if(lastUpdate != null && !PuntoControlConstants.EMPTY.equals(lastUpdate)){
                if(lastUpdate.equals(today)){
                    showMenu();
                }else{
                    loadUnidadOperativaFromServer(context, updateControl, today);
                }
            }else{
                loadUnidadOperativaFromServer(context, updateControl, today);
            }
        }else{
            showMenu();
        }
    }

    public void loadUnidadOperativaFromServer(final Context context, final PuntoControlUpdateControl updateControl, final String today){
        if(PuntoControlUtils.getProgressDialog().isShowing()){
            PuntoControlUtils.getProgressDialog(null, getResources().getString(R.string.waiting_load_unidad_operativa));
        }else{
            PuntoControlUtils.getProgressDialog(context, getResources().getString(R.string.waiting_load_unidad_operativa)).show();
        }

        AsyncHttpClient client = new AsyncHttpClient();
        String url = PuntoControlConstants.URL_UNIDADOPERATIVA_LIST;
        client.get(url,null ,new AsyncHttpResponseHandler() {

            @Override
            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                try {
                    PuntoControlUtils.getProgressDialog().dismiss();
                    List<UnidadOperativa> result = new ArrayList<>();
                    // JSON Object
                    JSONArray list = new JSONArray(new String(responseBody));
                    for(int i = 0; i < list.length(); i++){
                        JSONObject obj = list.getJSONObject(i);
                        UnidadOperativa unidadOperativa = new UnidadOperativa();
                        unidadOperativa.setCodigo(obj.getInt("codigo"));
                        unidadOperativa.setCodigoOsinergmin(obj.getString("codigoOsinergmin"));
                        unidadOperativa.setRegistroHidrocarburos(obj.getString("registroHidrocarburos"));
                        unidadOperativa.setRuc(obj.getString("ruc"));
                        unidadOperativa.setRazonSocial(obj.getString("razonSocial"));
                        unidadOperativa.setDireccion(obj.getString("direccion"));
                        unidadOperativa.setDepartamento(obj.getString("departamento"));
                        unidadOperativa.setProvincia(obj.getString("provincia"));
                        unidadOperativa.setDistrito(obj.getString("distrito"));
                        unidadOperativa.setTipo(obj.getString("tipo"));
                        unidadOperativa.setPlaca(obj.getString("placa"));
                        unidadOperativa.setCapacidad(obj.getDouble("capacidad"));
                        unidadOperativa.setFechaActualizacion(new Date());
                        unidadOperativa.setActivo(true);
                        result.add(unidadOperativa);
                    }
                    PuntoControlUtils.getProgressDialog(null, getResources().getString(R.string.waiting_load_unidad_operativa));
                    getUnidadOperativaService().saveUnidadOperativaListToLocal(context, result);
                    updateControl.saveUpdateDate(today);
                    List<OrdenPedido> ordenPedidoList = getOrdenPedidoService().getOrdenPedidoList(context, null);
                    PuntoControlUtils.getProgressDialog().dismiss();
                    if(ordenPedidoList == null || ordenPedidoList.size() == 0) {
                        if(PuntoControlConstants.progressDialog.isShowing()){
                            PuntoControlUtils.getProgressDialog(null, getResources().getString(R.string.waiting_load_orden_pedido));
                        }else {
                            PuntoControlUtils.getProgressDialog(context, getResources().getString(R.string.waiting_load_orden_pedido)).show();
                        }
                        findOrdenPedidoOnServer(context);
                    }else{
                        showMenu();
                    }
                    PuntoControlUtils.getProgressDialog().hide();
                } catch (Exception e) {
                    PuntoControlUtils.getProgressDialog().dismiss();
                    makeText(context, R.string.error_json_generic, Toast.LENGTH_LONG);
                }
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
                PuntoControlUtils.getProgressDialog().dismiss();
                if(statusCode == 404){
                    makeText(context, R.string.error_http_404, Toast.LENGTH_LONG);
                }
                // When Http response code is '500'
                else if(statusCode == 500){
                    makeText(context, R.string.error_http_500, Toast.LENGTH_LONG);
                }
                // When Http response code other than 404, 500
                else{
                    makeText(context, R.string.error_http_other, Toast.LENGTH_LONG);
                }
            }
        });
    }

    public void findOrdenPedidoOnServer(final Context context){
        if(PuntoControlUtils.getProgressDialog().isShowing()){
            PuntoControlUtils.getProgressDialog(null, getResources().getString(R.string.waiting_load_orden_pedido));
        }else{
            PuntoControlUtils.getProgressDialog(context, getResources().getString(R.string.waiting_load_orden_pedido)).show();
        }
        AsyncHttpClient client = new AsyncHttpClient();
        String url = PuntoControlConstants.URL_ORDENPEDIDO_LIST;
        client.get(url,null ,new AsyncHttpResponseHandler() {

            @Override
            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                try {
                    List<OrdenPedido> result = new ArrayList<>();
                    // JSON Object
                    JSONArray list = new JSONArray(new String(responseBody));
                    for(int i = 0; i < list.length(); i++){
                        JSONObject obj = list.getJSONObject(i);
                        OrdenPedido ordenPedido = new OrdenPedido();
                        ordenPedido.setCodigo(obj.getInt("codigo"));
                        ordenPedido.setPlaca(obj.getString("placa"));
                        ordenPedido.setCodigoAutorizacion(obj.getString("codigoAutorizacion"));
                        try {
                            ordenPedido.setNumeroFactura(obj.getString("numeroFactura"));
                        }catch(Exception e){
                            Log.d("<LoginActivity:findOrdenPedidoOnServer:numeroFactura>",e.getMessage());
                        }
                        try {
                            ordenPedido.setNumeroGuia(obj.getString("numeroGuia"));
                        }catch(Exception e){
                            Log.d("<LoginActivity:findOrdenPedidoOnServer:numeroGuia>",e.getMessage());
                        }
                        ordenPedido.setFechaDespacho(new Date(obj.getLong("fechaDespacho")));
                        try {
                            ordenPedido.setFechaVenta(new Date(obj.getLong("fechaVenta")));
                        }catch(Exception e) {
                            Log.d("<LoginActivity:findOrdenPedidoOnServer:fechaVenta>",e.getMessage());
                        }
                        ordenPedido.setEstado(obj.getString("estado"));
                        result.add(ordenPedido);
                    }
                    getOrdenPedidoService().saveOrdenPedidoListToLocal(context, result);
                    PuntoControlUtils.getProgressDialog().hide();
                    showMenu();
                } catch (Exception e) {
                    PuntoControlUtils.getProgressDialog().dismiss();
                    makeText(context, R.string.error_json_generic, Toast.LENGTH_LONG);
                }
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
                PuntoControlUtils.getProgressDialog().dismiss();
                if(statusCode == 404){
                    makeText(context, R.string.error_http_404, Toast.LENGTH_LONG);
                }
                // When Http response code is '500'
                else if(statusCode == 500){
                    makeText(context, R.string.error_http_500, Toast.LENGTH_LONG);
                }
                // When Http response code other than 404, 500
                else{
                    makeText(context, R.string.error_http_other, Toast.LENGTH_LONG);
                }
            }
        });
    }

    public void onBackPressed() {
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_HOME);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }

    @Override
    public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            onBackPressed();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
}